package sk.robocup.dvanastyhrac.tactics;

import robocup.component.ControllerNumbers;
import robocup.component.SConf;
import robocup.component.ControllerNumbers.PLAY_MODE;
import robocup.component.ControllerNumbers.TEAM;
import robocup.component.actionfactories.BasicActionFactory;
import robocup.component.geometry.Vektor;
import robocup.component.tactics.AbstractState;
import robocup.component.tactics.StateEvaluation;
import robocup.component.worldobjects.Ball;
import robocup.component.worldobjects.Player;
import sk.robocup.dvanastyhrac.actionfactories.AttentionToActionFactory12;
import sk.robocup.dvanastyhrac.tactics.formation.PlayerFormationInfo12.FORMATION;
import sk.robocup.dvanastyhrac.config.ConfigUtil;

public class FormationState12 extends AbstractState {

    private Vektor strategicPosition;
    private static int[] defenders = {2, 3, 4, 5, 7};

    public FormationState12(StateEvaluation parent) {
        super(parent);
        state = STATES.DUMMY_STATE;
    }

    /**
     * Metoda vrati najlepsiu akciu pre prechod na strategicku poziciu s tym,
     * ze namahu nastavuje podla potreby. Utocnici pri utoku sa viac snazia (viac sa aj namahaju)
     * a naopak obrancovia pri obrane sa viac snazia.
     */
    @Override
    public void calculateMainAction() {
        if (isDefender(getWorld().getSelfRef())) {
            if (getWorld().ballCanBeKickedByOpponent()) {
                mainAction = BasicActionFactory.moveToPos(getWorld(), strategicPosition,
                        ControllerNumbers.STAMINA_LEVEL.MEDIUM_LOW);
            } else {
                mainAction = BasicActionFactory.moveToPos(getWorld(), strategicPosition,
                        ControllerNumbers.STAMINA_LEVEL.MAX);
            }
        } else {
            if (getWorld().ballCanBeKickedByOther() && !getWorld().ballCanBeKickedByOpponent()) {
                mainAction = BasicActionFactory.moveToPos(getWorld(), strategicPosition,
                        ControllerNumbers.STAMINA_LEVEL.MEDIUM_LOW);
            } else {
                mainAction = BasicActionFactory.moveToPos(getWorld(), strategicPosition,
                        ControllerNumbers.STAMINA_LEVEL.MAX);
            }
        }
    }
    /*@Override
    public void calculateMainAction() {
    
    mainAction = BasicActionFactory.moveToPos(getWorld(), strategicPosition,
    ControllerNumbers.STAMINA_LEVEL.MAX);
    
    }*/

    @Override
    public boolean preCondition() {

        /*
         * if (checkPlayMode() && (getPlayer().getNumber() != 1) &&
         * (this.parent.
         * getBall().getDistance(SConf.getInstance().GOAL_POS_OTHER) < 30) &&
         * (this.parent.getPlayer().getDistance(FormationData
         * .getFormationPosition(getWorld().getSelfRef().getDefaultRole(),
         * false)) > 1) && (!getProphet().iAmFastestToBall())) return true; else
         */
        if (!checkPlayMode()) {
            return false;
        }
        if (!getWorld().getBallRef().isReliable()) {
            return false;
        }
        if (getProphet().iAmFastestToBall()) {
            return false;
        }


        if (getWorld().getBallRef().getPosition().getY() > 5) {
            FormationData12.currentFormation = FORMATION.valueOf(ConfigUtil.get().getSTRATEGY_ATTACK());
        }
        if (getWorld().getBallRef().getPosition().getY() < -5) {
            FormationData12.currentFormation = FORMATION.valueOf(ConfigUtil.get().getSTRATEGY_DEFENSE());
        }

        if ((getWorld().getPlayMode() == PLAY_MODE.GOAL_OTHER) || (getWorld().getPlayMode() == PLAY_MODE.GOAL_OWN) || (getWorld().getPlayMode() == PLAY_MODE.BEFORE_KICK_OFF)) {
            ConfigUtil.get().refreshStrategy();
        }
        /*
        if(getWorld().getGoalDiff() < 0)
        FormationData12.currentFormation = FORMATION.ATTACK_EVO;
        else
        FormationData12.currentFormation = FORMATION.DEFENSE_EVO;
         */
        strategicPosition = getStrategicPosition();



        if (getWorld().getMyPosition().getDistance(strategicPosition) >
                1.5 + Math.abs(getWorld().getMyPosition().getY() -
                getWorld().getBallRef().getPosition().getY()) / 10) {
            return true;
        }

        return false;
    }

    /**
     * Urcuje ci sa bude najblizsie lopta vhadzovat alebo vykopavat
     * Lopta sa bude vykopavat zo stredu ihriska
     * @param playMode
     * @return
     */
    private boolean isBeforeKickOff(PLAY_MODE playMode) {

        return playMode == PLAY_MODE.BEFORE_KICK_OFF || playMode == PLAY_MODE.GOAL_OWN || playMode == PLAY_MODE.GOAL_OTHER || playMode == PLAY_MODE.KICK_OFF_OWN || playMode == PLAY_MODE.KICK_OFF_OTHER;
    }

    private boolean isFreeKickOwn(PLAY_MODE playMode) {

        return playMode == PLAY_MODE.INDIRECT_FREE_KICK_OWN || playMode == PLAY_MODE.FREE_KICK_OWN;
    }

    private boolean isFreeKickOther(PLAY_MODE playMode) {

        return playMode == PLAY_MODE.INDIRECT_FREE_KICK_OTHER || playMode == PLAY_MODE.FREE_KICK_OTHER;
    }

    private boolean isDeadBallOwn(PLAY_MODE playMode) {

        //TODO nepreberame z Jahodovych princov rezimy hry:
        // OFFSIDE, FREE_KICK_FAULT a este BACK_PASS
        return playMode == PLAY_MODE.KICK_IN_OWN || isFreeKickOwn(playMode) || playMode == PLAY_MODE.CORNER_KICK_OWN || playMode == PLAY_MODE.KICK_OFF_OWN || playMode == PLAY_MODE.GOAL_KICK_OWN;
    }

    private boolean isDeadBallOther(PLAY_MODE playMode) {

        //TODO nepreberame z Jahodovych princov rezimy hry:
        // OFFSIDE, FREE_KICK_FAULT a este BACK_PASS
        return playMode == PLAY_MODE.KICK_IN_OTHER || isFreeKickOther(playMode) || playMode == PLAY_MODE.CORNER_KICK_OTHER || playMode == PLAY_MODE.KICK_OFF_OTHER || playMode == PLAY_MODE.GOAL_KICK_OTHER;
    }

    /**
     *
     * @return
     */
    public Vektor getStrategicPosition() {
        boolean ballInPosession = getProphet().inPossessionOfBall() == TEAM.WE;
        double maxY = Math.max(-0.5, getWorld().getOffsideY(true) - 1.5);
        Ball ballClone = getWorld().getBallRef().cloned();
        Vektor ballPos = ballClone.getPosition();

        if (ballInPosession &&
                getWorld().getMyPosition().getY() < ballPos.getY()) {
            maxY = Math.max(maxY, ballPos.getY());
        }

        if (getWorld().getPlayMode() == PLAY_MODE.GOAL_KICK_OTHER) {
            maxY = Math.min(maxY, FormationData12.PENALTY_Y - 1.0);
        } else if (isBeforeKickOff(getWorld().getPlayMode())) {
            maxY = Math.min(maxY, -2.0);
        }

        if (isBeforeKickOff(getWorld().getPlayMode())) {
            ballPos.setX(0);
            ballPos.setY(0);
        } else //TODO getTimeLastCatch ma byt v alebo tejto podmienke
        //ale od Jahodovych princov sme to neprebrali
        if (getWorld().getPlayMode() == PLAY_MODE.GOAL_KICK_OWN || ((isFreeKickOwn((getWorld().getPlayMode())) && (ballPos.getY() < -FormationData12.PENALTY_Y)))) {
            ballPos.setY(-FormationData12.PITCH_LENGTH / 4 + 5);
        } else if (!ballClone.isReliable()) {
            ballPos.setX(0);
            ballPos.setY(0);
        } else if (getWorld().getPlayMode() == PLAY_MODE.GOAL_KICK_OTHER || ((isFreeKickOther(getWorld().getPlayMode())) && (ballPos.getY() > FormationData12.PENALTY_Y))) {
            ballPos.setY(FormationData12.PENALTY_Y - 10);
        } else if (isFreeKickOther(getWorld().getPlayMode())) {
            ballPos.setY(ballPos.getY() - 5);
        } else if ((ballInPosession) && !(isDeadBallOwn(getWorld().getPlayMode()) || isDeadBallOwn(getWorld().getPlayMode()))) {
            ballPos.setY(ballPos.getY() + 5.0);
        } else if (ballPos.getY() < -FormationData12.PENALTY_Y + 5.0) {
            ballPos = ballClone.getFuturePos(3, SConf.getInstance().BALL_DECAY);
        }

        return FormationData12.getStrategicPosition(getPlayer().getNumber(),
                ballPos, maxY, ballInPosession, 0.8,
                FormationData12.currentFormation);
    }

    @Override
    protected double successBenefit() {
        return 0.01;
    }

    @Override
    protected double successProbability() {
        return 1;
    }

    @Override
    public void calculateAttentionToAction() {
        this.attentionToAction = AttentionToActionFactory12.getAttentionToAction(this);

        //if we got null, compute default
        if (this.attentionToAction == null) {
            super.calculateAttentionToAction();
        }
    }

    /**
     * Metoda vrati ci dany hrac je obranca
     * @param player hrac
     * @return true ak hrac je obranca
     */
    private static boolean isDefender(Player player) {
        for (int playerNumber : defenders) {
            if (player.getNumber() == playerNumber) {
                return true;
            }
        }
        return false;
    }
}
